﻿using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using System.Net.Mime;
using System.Text;
using System.Text.Json;
using JsonSerializer = System.Text.Json.JsonSerializer;
using HuiLian.BigData.Hdl.Options;
using HuiLian.BigData.Hdl.Message;
using HuiLian.BigData.Hdl.ViewModel;
using HuiLian.BigData.Hdl.HttpModel;
using HuiLian.Common;
using System.Net;
using System.Net.Http.Headers;

namespace HuiLian.BigData.Hdl.Helper
{
    public sealed class HttpHelper
    {
        private readonly IHttpClientFactory _httpClientFactory = null!;
        private readonly ILogger<HttpHelper> _logger = null!;
        private readonly ServerOption _options;
        private readonly HttpRequestUrlOption _httpRequestUrlOption;

        public HttpHelper(IHttpClientFactory httpClientFactory, ILogger<HttpHelper> logger, IOptions<ServerOption> options, IOptions<HttpRequestUrlOption> httpRequestUrlOption)
        {
            _logger = logger;
            _options = options.Value;
            _httpClientFactory = httpClientFactory;
            _httpRequestUrlOption = httpRequestUrlOption.Value;
        }
        /// <summary>
        /// 写日志
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="ex"></param>
        public void Log(string msg, Exception ex)
        {
            _logger.LogError(msg, ex);
        }
        /// <summary>
        /// 登录到服务器
        /// </summary>
        /// <param name="username">用户名</param>
        /// <param name="password">密码</param>
        /// <returns></returns>
        public async Task<LoginMessage> LoginAsync(string username, string password)
        {
            var result = await PostAsync<LoginMessage>($"{_options.Url}/api/Admin/Auth/Login", new { userName = username, password = password });

            return result;
        }

        /// <summary>
        /// 执行Get请求
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public async Task<string> GetAsync(string url)
        {
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            string result;
            try
            {
                // Make HTTP GET request
                result = await client.GetStringAsync(url);

                return result ?? "没有返回任何数据";
            }
            catch (Exception ex)
            {
                result = ex.Message;
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }

            return result;
        }
        public async Task<string> PostAsync(string url, object data)
        {
            string result = "";
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                var jsonOption = new JsonSerializerOptions(JsonSerializerDefaults.Web)
                {
                    PropertyNameCaseInsensitive = true
                };
                string ttt = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                //_logger.LogDebug(ttt);
                using StringContent json = new(ttt, Encoding.UTF8, MediaTypeNames.Application.Json);

                using HttpResponseMessage httpResponse = await client.PostAsync(url, json);

                httpResponse.EnsureSuccessStatusCode();

                result = await httpResponse.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                result += ex.Message;
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }
        public async Task<T> PostAsync<T>(string url, object data) where T : ApiResult, new()
        {
            T result = new();
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                var str = await PostAsync(url, data);

                result = JsonSerializer.Deserialize<T>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            }
            catch (Exception ex)
            {
                result.Code = 400;
                result.Msg = ex.Message;

                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }

        #region 含有Header和Auth的请求方法

        public async Task<string> PostAsync(string url, object data, List<RequestHeader> header)
        {
            string result = "";
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                var jsonOption = new JsonSerializerOptions(JsonSerializerDefaults.Web)
                {
                    PropertyNameCaseInsensitive = true
                };
                string ttt = Newtonsoft.Json.JsonConvert.SerializeObject(data);
                //_logger.LogDebug(ttt);
                using StringContent json = new(ttt, Encoding.UTF8, MediaTypeNames.Application.Json);

                if (header != null && header.Count > 0)
                {
                    foreach (var item in header)
                    {
                        client.DefaultRequestHeaders.Add(item.Name, item.Value);
                    }
                }

                using HttpResponseMessage httpResponse = await client.PostAsync(url, json);

                httpResponse.EnsureSuccessStatusCode();

                result = await httpResponse.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                result += ex.Message;
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }


        public async Task<T> PostAsync<T>(string url, object data, List<RequestHeader> header) where T : new()
        {
            T result = new();
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                var str = await PostAsync(url, data, header);

                result = JsonSerializer.Deserialize<T>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            }
            catch (Exception ex)
            {
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }

        #region UrlEncoded

        public async Task<string> PostFormUrlEncodedContentAsync(string url, Dictionary<string, string> dicData, List<RequestHeader> header)
        {
            string result = "";
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                FormUrlEncodedContent content = new FormUrlEncodedContent(dicData);

                if (header != null && header.Count > 0)
                {
                    foreach (var item in header)
                    {
                        client.DefaultRequestHeaders.Add(item.Name, item.Value);
                    }
                }

                using HttpResponseMessage httpResponse = await client.PostAsync(url, content);

                httpResponse.EnsureSuccessStatusCode();

                result = await httpResponse.Content.ReadAsStringAsync();
            }
            catch (Exception ex)
            {
                result += ex.Message;
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }


        public async Task<T> PostFormUrlEncodedContentAsync<T>(string url, Dictionary<string, string> dicData, List<RequestHeader> header) where T : new()
        {
            T result = new();
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                var str = await PostFormUrlEncodedContentAsync(url, dicData, header);

                result = JsonSerializer.Deserialize<T>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            }
            catch (Exception ex)
            {
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }

        #endregion

        #region Auth

        public async Task<string> PostAuthAsync(string url, object data, List<RequestHeader> header)
        {
            string result = "";
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();

            try
            {
                string ttt = Newtonsoft.Json.JsonConvert.SerializeObject(data);

                var request = new HttpRequestMessage
                {
                    Method = HttpMethod.Post,
                    RequestUri = new Uri(url),
                    Headers =
                    {
                        { "Accept", "*/*" },
                        { "User-Agent", "PostmanRuntime-ApipostRuntime/1.1.0" },
                        { "Connection", "keep-alive" },        
                    },
                    Content = new StringContent(ttt)
                    {
                        Headers =
                        {
                            ContentType = new MediaTypeHeaderValue("application/json")
                        }
                    }
                };

                if (header != null && header.Count > 0)
                {
                    foreach (var item in header)
                    {
                        request.Headers.Add(item.Name, item.Value);
                    }
                }

                using (var response = await client.SendAsync(request))
                {
                    response.EnsureSuccessStatusCode();
                    result = await response.Content.ReadAsStringAsync();
                }
            }
            catch (Exception ex)
            {
                result += ex.Message;
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
            }
            return result;
        }


        public async Task<T> PostAuthAsync<T>(string url, object data, List<RequestHeader> header) where T : new()
        {
            T result = new();
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();
            string str = string.Empty;
            try
            {
                str = await PostAuthAsync(url, data, header);
                
                result = JsonSerializer.Deserialize<T>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
            }
            catch (Exception ex)
            {
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
                _logger.LogDebug(str);
            }
            return result;
        }

        public async Task<T> PostAuth_WriteResultAsync<T>(string url, object data, List<RequestHeader> header, string fileName) where T : new()
        {
            T result = new();
            // 创建客户端
            using HttpClient client = _httpClientFactory.CreateClient();
            string str = string.Empty;
            try
            {
                str = await PostAuthAsync(url, data, header);

                result = JsonSerializer.Deserialize<T>(str, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });

                if (!string.IsNullOrEmpty(fileName))
                {
                    System.IO.File.WriteAllText(fileName, str);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError("请求:{0},时发生异常： {Error}", url, ex);
                _logger.LogDebug(str);
            }
            return result;
        }

        #endregion

        #endregion

        #region 大数据对接

        public async Task<RealmsZzssProtocolTokenResponse> RealmsZzssProtocolTokenResponseAsync()
        {
            Dictionary<string, string> dicData = new Dictionary<string, string> 
            {
                {"client_id","gwsb" },
                {"client_secret","1t0XuUdTRBt60wyU2fbZ2UVhaAKM7z0M" },
                {"grant_type","client_credentials" }
            };

            var result = await PostFormUrlEncodedContentAsync<RealmsZzssProtocolTokenResponse>(
                $"{_httpRequestUrlOption.RealmsZzssProtocolUrl}/realms/zzss/protocol/openid-connect/token",
                dicData,
                new List<RequestHeader>());

            return result;
        }

        #endregion

        #region 和达对接

        public async Task<HdlOauthAccessResponse> HdlOauthAccessResponseAsync(string client_id, string client_secret)
        {
            HdlOauthAccessRequest request = new HdlOauthAccessRequest();
            request.client_id = client_id;
            client_secret = (client_id + "$" + client_secret).Sha256().ToLower();
            request.client_secret = client_secret;
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                }
            };
            RequestHeader header = new RequestHeader
            {
                Name = "Authorization",
                Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
            };
            requestHeaders.Add(header);
            var result = await PostAuthAsync<HdlOauthAccessResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/oauth/v1.0/access.json",
                request,
                requestHeaders);

            return result;
        }

        /// <summary>
        /// 通用站点信息查询接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<HdlScadaStationInfoResponse> HdlScadaStationInfoResponseAsync(HdlScadaStationInfoRequest request)
        {
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Authorization",
                    Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
                },
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                },
                new RequestHeader
                {
                    Name = "Access_Token",
                    Value = GlobalVariable.HdlOauthAccessToken
                },
            };

            string directoryPath = @"station/info";
            string fileName = @$"{directoryPath}/_info.json";
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            var result = await PostAuth_WriteResultAsync<HdlScadaStationInfoResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/scada/v1.0/station/info.json",
                request,
                requestHeaders,
                fileName);

            return result;
        }

        /// <summary>
        /// 通用传感器信息查询接口
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<HdlScadaSensorInfoResponse> HdlScadaSensorInfoAsync(HdlScadaSensorInfoRequest request)
        {
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Authorization",
                    Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
                },
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                },
                new RequestHeader
                {
                    Name = "Access_Token",
                    Value = GlobalVariable.HdlOauthAccessToken
                },
            };

            string directoryPath = @"sensor/info";
            string fileName = @$"{directoryPath}/_info.json";
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            var result = await PostAuth_WriteResultAsync<HdlScadaSensorInfoResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/scada/v1.0/sensor/info.json",
                request,
                requestHeaders,
                fileName);

            return result;
        }

        /// <summary>
        /// 实时数据
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public async Task<HdlScadaSensorRealTimeResponse> HdlScadaSensorRealTimeAsync(HdlScadaSensorRealTimeRequest request)
        {
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Authorization",
                    Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
                },
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                },
                new RequestHeader
                {
                    Name = "Access_Token",
                    Value = GlobalVariable.HdlOauthAccessToken
                },
            };

            string directoryPath = @"sensor/realtime";
            string fileName = @$"{directoryPath}/_realtime.json";
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            var result = await PostAuth_WriteResultAsync<HdlScadaSensorRealTimeResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/scada/v1.0/sensor/realtime.json",
                request,
                requestHeaders,
                fileName);

            return result;
        }

        public async Task<HdlScadaSensorHistoryResponse> HdlScadaSensorHistoryAsync(HdlScadaSensorHistoryRequest request)
        {
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Authorization",
                    Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
                },
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                },
                new RequestHeader
                {
                    Name = "Access_Token",
                    Value = GlobalVariable.HdlOauthAccessToken
                },
            };

            string directoryPath = @$"sensor/history/{request.codes[0]}";
            string fileName = @$"{directoryPath}/_{request.begin}_{request.end}_history.json";
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }

            var result = await PostAuth_WriteResultAsync<HdlScadaSensorHistoryResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/scada/v1.0/sensor/history.json",
                request,
                requestHeaders,
                fileName);

            return result;
        }

        #endregion

        #region 报警记录

        public async Task<HdlScadaAlarmHistoryResponse> HdlScadaAlarmHistoryAsync(HdlScadaAlarmHistoryRequest request)
        {            
            List<RequestHeader> requestHeaders = new List<RequestHeader>()
            {
                new RequestHeader
                {
                    Name = "Authorization",
                    Value = $"Bearer {GlobalVariable.RealmsZzssProtocolToken}"
                },
                new RequestHeader
                {
                    Name = "Host",
                    Value = "scada"
                },
                new RequestHeader
                {
                    Name = "Access_Token",
                    Value = GlobalVariable.HdlOauthAccessToken
                },
            };

            //创建文件夹
            string directoryPath = @"alarm/history";
            string fileName = @$"{directoryPath}/_{request.stimeBegin}_{request.stimeEnd}_{request.index}_{request.size}.json";            
            if (!Directory.Exists(directoryPath))
            {
                Directory.CreateDirectory(directoryPath);
            }
            
            var result = await PostAuth_WriteResultAsync<HdlScadaAlarmHistoryResponse>(
                $"{_httpRequestUrlOption.HdlUrl}/hdl/scada/v1.0/alarm/history.json",
                request,
                requestHeaders,
                fileName);

            return result;
        }


        #endregion
    }
}
